using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using XRPGLibrary.SpriteClasses;

namespace XRPGLibrary.TileEngine
{
    public enum CameraMode {Free, Follow}

    public class Camera
    {
        private float speed;
        private Vector2 position;
        private Rectangle viewportRectangle;

        public Vector2 Position
        {
            get { return position; }
            private set { position = value; }
        }
        public float Speed
        {
            get { return speed; }
            set { speed = (float) MathHelper.Clamp(speed, 1f, 16f); }
        }
        public float Zoom { get; private set; }
        public CameraMode Mode { get; private set; }
        public Matrix Transformation
        {
            get { return Matrix.CreateScale(Zoom)*Matrix.CreateTranslation(new Vector3(-Position, 0f)); }
        }

        public Rectangle ViewportRectangle
        {
            get { return new Rectangle(
                viewportRectangle.X,
                viewportRectangle.Y,
                viewportRectangle.Width,
                viewportRectangle.Height); }
        }

        public Camera(Rectangle viewportRect)
        {
            speed = 4f;
            Zoom = 1f;
            viewportRectangle = viewportRect;
            Mode = CameraMode.Follow;
        }

        public Camera(Rectangle viewportRect, Vector2 position)
        {
            speed = 4f;
            Zoom = 1f;
            viewportRectangle = viewportRect;
            Position = position;
            Mode = CameraMode.Follow;
        }

        public void Update(GameTime gameTime)
        {

            if (Mode == CameraMode.Follow)
                return;

            var motion = Vector2.Zero;

            if (InputHandler.KeyDown(Keys.Left))
                motion.X = -speed;
            else if (InputHandler.KeyDown(Keys.Right))
                motion.X = speed;

            if (InputHandler.KeyDown(Keys.Up))
                motion.Y = -speed;
            else if (InputHandler.KeyDown(Keys.Down))
                motion.Y = speed;

            if (motion != Vector2.Zero)
            {
                motion.Normalize();
                position += motion * speed;
                LockCamera();
            }

        }

        public void ZoomIn()
        {
            Zoom += .25f;
            if (Zoom > 2.5f)
                Zoom = 2.5f;

            Vector2 newPosition = Position*Zoom;
            SnapToPosition(newPosition);
        }

        public void ZoomOut()
        {
            Zoom -= .25f;
            if (Zoom < .5f)
                Zoom = .5f;
            Vector2 newPosition = Position*Zoom;
            SnapToPosition(newPosition);
        }

        private void SnapToPosition(Vector2 newPosition)
        {
            position.X = newPosition.X - viewportRectangle.Width/2;
            position.Y = newPosition.Y - viewportRectangle.Height/2;
            LockCamera();
        }

        private void LockCamera()
        {
            position.X = MathHelper.Clamp(
                position.X, 
                0, 
                TileMap.WidthInPixels * Zoom - viewportRectangle.Width);
            position.Y = MathHelper.Clamp(
                position.Y, 
                0, 
                TileMap.HeightInPixels * Zoom - viewportRectangle.Height);
        }

        public void LockToSprite(AnimatedSprite sprite)
        {
            position.X = (sprite.Position.X + sprite.Width/2) * Zoom - (viewportRectangle.Width/2);
            position.Y = (sprite.Position.Y + sprite.Height/2) * Zoom - (viewportRectangle.Height/2);
            LockCamera();
        }

        public void ToggleCameraMode()
        {
            if (Mode == CameraMode.Follow)
                Mode = CameraMode.Free;
            else if (Mode == CameraMode.Free)
                Mode = CameraMode.Follow;
        }
    }
}